# -*- coding: utf-8 -*-
import json

from marshmallow import Schema, fields, validates, ValidationError
from marshmallow.fields import List


class BaseSchema(Schema):
    pass


class PaginationSchema(Schema):
    """
    分页接口参数基类检查器.
    """
    page_no = fields.Integer(missing=1)
    page_size = fields.Integer(missing=30)

    @validates('page_size')
    def validate_page_size(self, value):
        if value < 1:
            raise ValidationError('page_size must great 0')
        if value > 5000:
            raise ValidationError('page_size must less 1000')


class CNDatetimeField(fields.DateTime):
    """
    中国地区常用的 2018-01-01 12:00:00 格式，区别于iso的 2018-01-01T12:00:00
    """
    DEFAULT_FORMAT = '%Y-%m-%d %H:%M:%S'


class OptionField(fields.Field):
    """
    从预置数据列表中选择一项
    """

    def __init__(self, options, *args, **kwargs):
        assert isinstance(options, list)
        assert options, 'options must not empty'
        self.options = options
        self.value_type = type(options[0])
        for each in options:
            if self.value_type != type(each):
                assert 'each value in options must be same type'

        super(OptionField, self).__init__(*args, **kwargs)

    def _deserialize(self, value, attr, data, **kwargs):
        try:
            value = self.value_type(value)
            if value not in self.options:
                raise ValidationError('value: <{}> is not in options: {}'.format(value, self.options))
            return value
        except ValueError:
            raise ValidationError('value: <{}> type is not {}'.format(value, self.value_type))


class GenericList(List):
    def _deserialize(self, value, attr, data, **kwargs):
        if isinstance(value, str):
            try:
                value = json.loads(value)
            except ValueError:
                raise ValidationError('value: <{}> type is not list type'.format(value))

        return super(GenericList, self)._deserialize(value, attr, data, **kwargs)
